package com.jfinal.ext.plugin.shiro;

import com.hz.foodstalls.model.*;
import com.jfinal.config.Routes;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.IPlugin;
import org.apache.shiro.authz.annotation.*;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author fupan
 * @description 动态权限插件
 * @create 2017-08-25 17:06
 **/
@SuppressWarnings("unchecked")
public class JdbcShiroPlugin implements IPlugin {

    private static final String SLASH = "/";

    /**
     * Shiro的几种访问控制注解
     */
    private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES = new Class[]{
            RequiresPermissions.class, RequiresRoles.class, RequiresUser.class, RequiresGuest.class,
            RequiresAuthentication.class};

    /**
     * 路由设定
     */
    private final List<Routes.Route> routes;

    /**
     * 构造函数
     *
     * @param routes 路由设定
     */
    public JdbcShiroPlugin(List<Routes.Route> routes) {
        this.routes = routes;
    }

    /**
     * 停止插件
     */
    @Override
    public boolean stop() {
        return true;
    }

    /**
     * 启动插件
     */
    @Override
    public boolean start() {
        setAuthzMaps();
        return true;
    }

    /**
     * 设置动态菜单缓存
     *
     * @param controller
     */
    public static void setMenu(Controller controller) {
        String username = controller.getSessionAttr("username");
        Admin admin = Admin.dao.getAdminByUsername(username);
        List<Resource> resources = new ArrayList<>();
        AdminRole adminRole = AdminRole.dao.findFirst("select * from admin_role where adminSet_id = ?", admin.getId());
        if (adminRole != null) {
            Role role = Role.dao.findById(adminRole.getRolesetId());
            List<RoleResource> roleResources = RoleResource.dao.findRoleResourcesByRoleid(role.getId());
            for (int i = 0; i < roleResources.size(); i++) {
                RoleResource roleResource = roleResources.get(i);
                Resource resource = Resource.dao.findById(roleResource.getResourcesetId());
                resources.add(resource);
            }
        }
        List<Map> list = new ArrayList<>();
        for (int i = 0; i < resources.size(); i++) {
            Resource resource = resources.get(i);
            Map<String, Object> parentMap = new HashMap<>();
            if (resource.getPid() == 0) {
                parentMap.put("name", resource.getName());
                parentMap.put("order", resource.getOrderList());
                List<Map> child = new ArrayList<>();
                List childMenu = new ArrayList();
                for (int j = 0; j < resources.size(); j++) {
                    Resource resourceInit = resources.get(j);
                    Map<String, Object> childMap = new HashMap<>();
                    if (resourceInit.getPid().equals(resource.getId())) {
                        childMap.put("name", resourceInit.getName());
                        childMap.put("order", resourceInit.getOrderList());
                        String action = resourceInit.getAction().split(",")[0];
                        childMap.put("action", action);
                        childMenu.add("/" + action);
                        child.add(childMap);
                    }
                }
                parentMap.put("childMenu", childMenu.toArray());
                parentMap.put("child", child);
                list.add(parentMap);
            }
        }
        controller.setSessionAttr("treeviews", list);
    }

    /**
     * 设置权限缓存
     */
    private static void setAuthzMaps() {
        ConcurrentMap<String, AuthzHandler> authzMaps = new ConcurrentHashMap<String, AuthzHandler>();
        List<Resource> resources = Resource.dao.findAllResource();//所有的菜单
        for (Resource resource : resources) {//遍历菜单
            List<RoleResource> roleResources = RoleResource.dao.find("select *from role_resource where resourceSet_id=?", resource.getId());//获取菜单权限
            String[] rolenames = new String[roleResources.size()];
            for (int i = 0; i < roleResources.size(); i++) {//获取菜单角色
                RoleResource roleResource = roleResources.get(i);
                Role role = Role.dao.findById(roleResource.getRolesetId());
                rolenames[i] = role.getValue();
            }
            if (StrKit.notBlank(resource.getAction())) {
                for (String url : resource.getAction().split(",")) {
                    authzMaps.put("/" + url, new JdbcRoleAuthzHandler(rolenames));
                }
            }
        }
        ShiroKit.init(authzMaps);
    }

    /**
     * 重设缓存
     *
     * @param controller
     */
    public static void reSetShiro(Controller controller) {
        setAuthzMaps();
        setMenu(controller);
    }
}
